import { EventEmitter } from 'events';
import WebSocket from 'ws';
import { RemoteConfig } from '../remote';

/**
 * WebSocket 客户端，用于与远程端点通信
 */
export class WebSocketClient extends EventEmitter {
  private ws: WebSocket | null = null;
  private reconnectAttempts: number = 0;
  private readonly maxReconnectAttempts: number = 5;
  private readonly initialReconnectDelay: number = 1000;
  private readonly config: RemoteConfig;

  /**
   * 创建 WebSocket 客户端
   * @param config 远程配置
   */
  constructor(config: RemoteConfig) {
    super();
    this.config = config;
    console.log(`[WS_CLIENT] Created with config:`, {
      hasSerializer: !!config.serializer,
      hostname: config.hostname,
      port: config.port
    });
  }

  /**
   * 连接到指定主机和端口
   * @param hostname 主机名
   * @param port 端口号
   */
  async connect(hostname: string, port: number): Promise<void> {
    if (this.ws) {
      console.log(`[WS_CLIENT] Already connected, closing existing connection`);
      this.ws.close();
      this.ws = null;
    }

    return new Promise<void>((resolve, reject) => {
      try {
        console.log(`[WS_CLIENT] Connecting to ws://${hostname}:${port}`);
        this.ws = new WebSocket(`ws://${hostname}:${port}`);

        this.ws.onopen = () => {
          console.log(`[WS_CLIENT] WebSocket connection established to ws://${hostname}:${port}`);
          this.reconnectAttempts = 0;
          this.emit('connected');
          resolve();
        };

        this.ws.onclose = (event) => {
          console.log(`[WS_CLIENT] WebSocket connection closed: ${event.code} - ${event.reason || 'No reason provided'}`);
          this.ws = null;
          this.emit('disconnected');
          if (this.reconnectAttempts === 0) {
            // 只有在首次连接失败时才拒绝Promise
            reject(new Error(`Connection closed: ${event.code} - ${event.reason || 'No reason provided'}`));
          }
        };

        this.ws.onerror = (event) => {
          console.error(`[WS_CLIENT] WebSocket error:`, event);
          const error = new Error('WebSocket connection error');
          this.emit('error', error);
          reject(error);
        };

        this.ws.onmessage = (event) => {
          try {
            console.log(`[WS_CLIENT] Received message, data type: ${typeof event.data}`);
            
            let parsedMessage;
            try {
              parsedMessage = JSON.parse(event.data as string);
              console.log(`[WS_CLIENT] Successfully parsed message, type: ${parsedMessage.type}`);
            } catch (parseError) {
              console.error(`[WS_CLIENT] Failed to parse message:`, parseError);
              console.log(`[WS_CLIENT] Raw message data:`, typeof event.data === 'string' ? event.data.substring(0, 100) + '...' : '(binary data)');
              return;
            }
            
            if (this.config.serializer) {
              try {
                console.log(`[WS_CLIENT] Using serializer to deserialize message`);
                const deserialized = this.config.serializer.deserialize(parsedMessage);
                console.log(`[WS_CLIENT] Message successfully deserialized`);
                this.emit('message', deserialized);
              } catch (deserializeError) {
                console.error(`[WS_CLIENT] Deserialization error:`, deserializeError);
                // 尝试直接发送解析后的消息
                console.log(`[WS_CLIENT] Falling back to parsed JSON message`);
                this.emit('message', parsedMessage);
              }
            } else {
              // 无序列化器，直接发送解析后的JSON
              console.log(`[WS_CLIENT] No serializer configured, emitting parsed JSON`);
              this.emit('message', parsedMessage);
            }
          } catch (error) {
            console.error(`[WS_CLIENT] Error handling message:`, error);
            this.emit('error', error);
          }
        };
      } catch (error) {
        console.error(`[WS_CLIENT] Error creating WebSocket:`, error);
        reject(error);
      }
    });
  }

  /**
   * 发送消息
   * @param message 要发送的消息
   */
  async send(data: string): Promise<void> {
    return new Promise<void>((resolve, reject) => {
      if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
        const error = new Error(`Cannot send message: WebSocket is ${!this.ws ? 'not initialized' : `in state ${this.ws.readyState}`}`);
        console.error(`[WS_CLIENT] ${error.message}`);
        reject(error);
        return;
      }

      try {
        console.log(`[WS_CLIENT] Sending message, length: ${data.length}`);
        this.ws.send(data);
        console.log(`[WS_CLIENT] Message sent successfully`);
        resolve();
      } catch (error) {
        console.error(`[WS_CLIENT] Error sending message:`, error);
        reject(error);
      }
    });
  }

  /**
   * 关闭连接
   */
  close(): void {
    console.log(`[WS_CLIENT] Closing WebSocket connection`);
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
  }

  isConnected(): boolean {
    return !!this.ws && this.ws.readyState === WebSocket.OPEN;
  }
} 